/**
 * 
 */
package edu.rit.cs.web.pages;

import java.util.Arrays;
import java.util.List;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponentLabel;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.StatelessForm;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;

import edu.rit.cs.core.pojos.AUser;
import edu.rit.cs.core.pojos.Administrator;
import edu.rit.cs.core.pojos.Customer;
import edu.rit.cs.core.services.daos.AdministratorDAO;
import edu.rit.cs.core.services.daos.CustomerDAO;

/**
 * A page for creating users of the type customer and administrator to use
 * their respective sections.
 * 
 * @see AdminPage
 * @see CustomerPage
 * 
 * @author Abhishek Shrestha (axs1430)
 * @author Juan Saldana (jjs6109)
 * @author Victor Alvarez (vxa1557)
 */
public class CreateUserPage extends WebPage {

  @SpringBean
  private CustomerDAO cd;
  @SpringBean
  private AdministratorDAO ad;

  public CreateUserPage(PageParameters parameters) {
    super(parameters);

    final FeedbackPanel fp = new FeedbackPanel("feedback");

    final WebMarkupContainer container = new WebMarkupContainer("container");
    container.setOutputMarkupId(true);

    @SuppressWarnings("serial")
    final Form<AUser> form = new StatelessForm<AUser>("form",
            new CompoundPropertyModel<AUser>(new AUser() {}));
    final TextField<String> tf = new RequiredTextField<String>("username");

    final TextField<String> pf = new PasswordTextField("password");

    final List<String> typesList = Arrays.asList("Customer", "Administrator"); 
    final DropDownChoice<String> type = new DropDownChoice<String>("type", 
            new Model<String>(typesList.get(0)), typesList);

    /* the submit button */
    final Button submitBtn = new AjaxButton("submitBtn", form) {
      private static final long serialVersionUID = 1L;

      @Override
      protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
        target.add(container);

        AUser user = (AUser) form.getModelObject();
        if (typesList.get(0).equals(type.getConvertedInput())) {
          Customer customer = new Customer();
          customer.setUsername(user.getUsername());
          customer.setPlainPassword(user.getPassword());
          try {
            cd.save(customer);
            fp.info("Alrighty! Customer created.");

          } catch (RuntimeException s) {
            error("Oops, duplicate username for Customer.");
          }

        } else {
          Administrator administrator = new Administrator();
          administrator.setUsername(user.getUsername());
          administrator.setPlainPassword(user.getPassword());
          try {
            ad.save(administrator);
            fp.info("Alrighty! Administrator created.");

          } catch (RuntimeException s) {
            error("Oops, duplicate username for Administrator.");
          }
        } // end of if
      } // end of onSubmit
      
      @Override
      protected void onError(AjaxRequestTarget target, Form<?> form) {
        target.add(container);
      }
    };

    /* list of existing users */
    container.add(new UserListView<AUser>("customers",
            new CustomerListDetachableModel()));
    container.add(new UserListView<AUser>("admins",
            new AdminListDetachableModel()));

    /* add the form labels */
    form.add(new FormComponentLabel("usernameLbl", tf));
    form.add(new FormComponentLabel("passwordLbl", pf));
    form.add(new FormComponentLabel("typeLbl", type));

    /* add the components */
    form.add(tf);
    form.add(pf);
    form.add(type);
    form.add(submitBtn);
    container.add(fp);
    container.add(form);
    add(container);
  }

  /**
   * A list for displaying the user information.
   * 
   * @author Abhishek Shrestha (axs1430)
   * @author Juan Saldana (jjs6109)
   * @author Victor Alvarez (vxa1557)
   * 
   * @param <T> The type of user to display in the list.
   * @see Administrator
   * @see Customer
   */
  private class UserListView<T extends AUser> extends ListView<T> {
    private static final long serialVersionUID = 1L;

    public UserListView(String id, IModel<? extends List<? extends T>> model) {
      super(id, model);
    }

    @Override
    protected void populateItem(ListItem<T> item) {
      item.setModel(new CompoundPropertyModel<T>(item.getModelObject()));
      item.add(new Label("id"));
      item.add(new Label("username"));
      item.add(new Label("password"));
    }
  };

  /**
   * A model containing the list of all the {@link Customer}s.
   * 
   * @author Abhishek Shrestha (axs1430)
   * @author Juan Saldana (jjs6109)
   * @author Victor Alvarez (vxa1557)
   */
  private class CustomerListDetachableModel
    extends LoadableDetachableModel<List<Customer>> {

    private static final long serialVersionUID = 1L;

    @Override
    protected List<Customer> load() {
      return cd.findAll();
    }
  }

  /**
   * A model containing the list of all the {@link Administrator}s.
   * 
   * @author Abhishek Shrestha (axs1430)
   * @author Juan Saldana (jjs6109)
   * @author Victor Alvarez (vxa1557)
   */
  private class AdminListDetachableModel
    extends LoadableDetachableModel<List<Administrator>> {

    private static final long serialVersionUID = 1L;
    
    @Override
    protected List<Administrator> load() {
      return ad.findAll();
    }
  }
}
